home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / Other Langs / python / Lib / sched.py < prev    next >
Encoding:
Python Source  |  1994-04-01  |  3.7 KB  |  101 lines  |  [TEXT/R*ch]

  1. # Module sched -- a generally useful event scheduler class
  2.  
  3. # Each instance of this class manages its own queue.
  4. # No multi-threading is implied; you are supposed to hack that
  5. # yourself, or use a single instance per application.
  6. #
  7. # Each instance is parametrized with two functions, one that is
  8. # supposed to return the current time, one that is supposed to
  9. # implement a delay.  You can implement fine- or course-grained
  10. # real-time scheduling by substituting time and sleep or millitimer
  11. # and millisleep from the built-in module time, or you can implement
  12. # simulated time by writing your own functions.  This can also be
  13. # used to integrate scheduling with STDWIN events; the delay function
  14. # is allowed to modify the queue.  Time can be expressed as
  15. # integers or floating point numbers, as long as it is consistent.
  16.  
  17. # Events are specified by tuples (time, priority, action, argument).
  18. # As in UNIX, lower priority numbers mean higher priority; in this
  19. # way the queue can be maintained fully sorted.  Execution of the
  20. # event means calling the action function, passing it the argument.
  21. # Remember that in Python, multiple function arguments can be packed
  22. # in a tuple.   The action function may be an instance method so it
  23. # has another way to reference private data (besides global variables).
  24. # Parameterless functions or methods cannot be used, however.
  25.  
  26. # XXX The timefunc and delayfunc should have been defined as methods
  27. # XXX so you can define new kinds of schedulers using subclassing
  28. # XXX instead of having to define a module or class just to hold
  29. # XXX the global state of your particular time and delay functtions.
  30.  
  31. import bisect
  32.  
  33. class scheduler:
  34.     #
  35.     # Initialize a new instance, passing the time and delay functions
  36.     #
  37.     def __init__(self, timefunc, delayfunc):
  38.         self.queue = []
  39.         self.timefunc = timefunc
  40.         self.delayfunc = delayfunc
  41.     #
  42.     # Enter a new event in the queue at an absolute time.
  43.     # Returns an ID for the event which can be used
  44.     # to remove it, if necessary.
  45.     #
  46.     def enterabs(self, time, priority, action, argument):
  47.         event = time, priority, action, argument
  48.         bisect.insort(self.queue, event)
  49.         return event # The ID
  50.     #
  51.     # A variant that specifies the time as a relative time.
  52.     # This is actually the more commonly used interface.
  53.     #
  54.     def enter(self, delay, priority, action, argument):
  55.         time = self.timefunc() + delay
  56.         return self.enterabs(time, priority, action, argument)
  57.     #
  58.     # Remove an event from the queue.
  59.     # This must be presented the ID as returned by enter().
  60.     # If the event is not in the queue, this raises RuntimeError.
  61.     #
  62.     def cancel(self, event):
  63.         self.queue.remove(event)
  64.     #
  65.     # Check whether the queue is empty.
  66.     #
  67.     def empty(self):
  68.         return len(self.queue) == 0
  69.     #
  70.     # Run: execute events until the queue is empty.
  71.     #
  72.     # When there is a positive delay until the first event, the
  73.     # delay function is called and the event is left in the queue;
  74.     # otherwise, the event is removed from the queue and executed
  75.     # (its action function is called, passing it the argument).
  76.     # If the delay function returns prematurely, it is simply
  77.     # restarted.
  78.     #
  79.     # It is legal for both the delay function and the action
  80.     # function to to modify the queue or to raise an exception;
  81.     # exceptions are not caught but the scheduler's state
  82.     # remains well-defined so run() may be called again.
  83.     #
  84.     # A questionably hack is added to allow other threads to run:
  85.     # just after an event is executed, a delay of 0 is executed,
  86.     # to avoid monopolizing the CPU when other threads are also
  87.     # runnable.
  88.     #
  89.     def run(self):
  90.         q = self.queue
  91.         while q:
  92.             time, priority, action, argument = q[0]
  93.             now = self.timefunc()
  94.             if now < time:
  95.                 self.delayfunc(time - now)
  96.             else:
  97.                 del q[0]
  98.                 void = apply(action, argument)
  99.                 self.delayfunc(0) # Let other threads run
  100.     #
  101.